﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.AccessControl;
using System.IO;
using System.Security.Principal;

namespace Security2
{
    #region Enums
    public enum ApplyTo
    {
        ThisFolderOnly = 1, //InheritanceFlags None / PropagationFlags None
        ThisFolderSubfoldersAndFiles = 2, //InheritanceFlags ContainerInherit, ObjectInherit / PropagationFlags None
        ThisFolderAndSubfolders = 3, //InheritanceFlags ContainerInherit / PropagationFlags None
        ThisFolderAndFiles = 4, //InheritanceFlags ObjectInherit / PropagationFlags None
        SubfoldersAndFilesOnly = 5, //InheritanceFlags ContainerInherit, ObjectInherit / PropagationFlags InheritOnly
        SubfolersOnly = 6, //InheritanceFlags ContainerInherit / PropagationFlags InheritOnly
        FilesOnly = 7 //InheritanceFlags ObjectInherit / PropagationFlags InheritOnly
    }

    [Flags]
    public enum FileSystemRights2 : uint
    {
        None = 0,
        ReadData = 1,
        CreateFiles = 2,
        AppendData = 4,
        ReadExtendedAttributes = 8,
        WriteExtendedAttributes = 16,
        ExecuteFile = 32,
        DeleteSubdirectoriesAndFiles = 64,
        ReadAttributes = 128,
        WriteAttributes = 256,
        Write = 278,
        Delete = 65536,
        ReadPermissions = 131072,
        Read = 131209,
        ReadAndExecute = 131241,
        Modify = 197055,
        ChangePermissions = 262144,
        TakeOwnership = 524288,
        Synchronize = 1048576,
        FullControl = 2032127,
        GenericRead = 0x80000000,
        GenericWrite = 0x40000000,
        GenericExecute = 0x20000000,
        GenericAll = 0x10000000
    }

    [Flags]
    public enum SimpleFileSystemAccessRights
    {
        None = 0,
        Read = 1,
        Write = 2,
        Delete = 4
    }

    public enum GenericRights : uint
    {
        GENERIC_READ = 0x80000000,
        GENERIC_WRITE = 0x40000000,
        GENERIC_EXECUTE = 0x20000000,
        GENERIC_ALL = 0x10000000
    }

    public enum MappedGenericRights : uint
    {
        FILE_GENERIC_EXECUTE = FileSystemRights.ExecuteFile | FileSystemRights.ReadPermissions | FileSystemRights.ReadAttributes | FileSystemRights.Synchronize,
        FILE_GENERIC_READ = FileSystemRights.ReadAttributes | FileSystemRights.ReadData | FileSystemRights.ReadExtendedAttributes | FileSystemRights.ReadPermissions | FileSystemRights.Synchronize,
        FILE_GENERIC_WRITE = FileSystemRights.AppendData | FileSystemRights.WriteAttributes | FileSystemRights.WriteData | FileSystemRights.WriteExtendedAttributes | FileSystemRights.ReadPermissions | FileSystemRights.Synchronize,
        FILE_GENERIC_ALL = FileSystemRights.FullControl
    }
    #endregion

    public class FileSystemFlags
    {
        public System.Security.AccessControl.InheritanceFlags InheritanceFlags { get; set; }
        public System.Security.AccessControl.PropagationFlags PropagationFlags { get; set; }
    }

    public class RightsConverionException : Exception
    {
        public RightsConverionException(string Message) : base(Message) { }
    }

    #region FileSystemSecurity2
    public class FileSystemSecurity2
    {
        protected FileSecurity fileSecurityDescriptor;
        protected DirectorySecurity directorySecurityDescriptor;
        protected FileSystemInfo item;
        protected FileSystemSecurity sd;
        protected bool isFile = false;

        public string FullName { get { return item.FullName; } }

        public string Name { get { return System.IO.Path.GetFileName(item.FullName); } }

        public bool IsFile { get { return isFile; } }

        public FileSystemSecurity2(FileSystemInfo item)
        {
            if (item is FileInfo)
            {
                this.item = (FileInfo)item;
                sd = ((FileInfo)this.item).GetAccessControl(AccessControlSections.Access);
            }
            else
            {
                this.item = (DirectoryInfo)item;
                sd = ((DirectoryInfo)this.item).GetAccessControl(AccessControlSections.Access);
            }
        }

        #region Conversion
        public static implicit operator FileSecurity(FileSystemSecurity2 fs2)
        {
            return fs2.fileSecurityDescriptor;
        }
        public static implicit operator FileSystemSecurity2(FileSecurity fs)
        {
            return new FileSystemSecurity2(new FileInfo(""));
        }

        //REQUIRED BECAUSE OF CONVERSION OPERATORS
        public override bool Equals(object obj)
        {
            return this.fileSecurityDescriptor == (FileSecurity)obj;
        }
        public override int GetHashCode()
        {
            return this.fileSecurityDescriptor.GetHashCode();
        }
        #endregion

        public static void ConvertToFileSystemFlags(ApplyTo ApplyTo, out InheritanceFlags inheritanceFlags, out PropagationFlags propagationFlags)
        {
            inheritanceFlags = InheritanceFlags.None;
            propagationFlags = PropagationFlags.None;

            switch (ApplyTo)
            {
                case ApplyTo.FilesOnly:
                    inheritanceFlags = InheritanceFlags.ObjectInherit;
                    propagationFlags = PropagationFlags.InheritOnly;
                    break;
                case Security2.ApplyTo.SubfoldersAndFilesOnly:
                    inheritanceFlags = InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit;
                    propagationFlags = PropagationFlags.InheritOnly;
                    break;
                case Security2.ApplyTo.SubfolersOnly:
                    inheritanceFlags = InheritanceFlags.ContainerInherit;
                    propagationFlags = PropagationFlags.None;
                    break;
                case Security2.ApplyTo.ThisFolderAndFiles:
                    inheritanceFlags = InheritanceFlags.ObjectInherit;
                    propagationFlags = PropagationFlags.None;
                    break;
                case Security2.ApplyTo.ThisFolderAndSubfolders:
                    inheritanceFlags = InheritanceFlags.ContainerInherit;
                    propagationFlags = PropagationFlags.None;
                    break;
                case Security2.ApplyTo.ThisFolderOnly:
                    inheritanceFlags = InheritanceFlags.None;
                    propagationFlags = PropagationFlags.None;
                    break;
                case Security2.ApplyTo.ThisFolderSubfoldersAndFiles:
                    inheritanceFlags = InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit;
                    propagationFlags = PropagationFlags.None;
                    break;
            }
        }

        public static ApplyTo ConvertToApplyTo(InheritanceFlags InheritanceFlags, PropagationFlags PropagationFlags)
        {
            if (InheritanceFlags == InheritanceFlags.ObjectInherit & PropagationFlags == PropagationFlags.InheritOnly)
            {
                return ApplyTo.FilesOnly;
            }
            else if (InheritanceFlags == (InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit) & PropagationFlags == PropagationFlags.InheritOnly)
            {
                return ApplyTo.SubfoldersAndFilesOnly;
            }
            else if (InheritanceFlags == InheritanceFlags.ContainerInherit & PropagationFlags == PropagationFlags.None)
            {
                return ApplyTo.SubfolersOnly;
            }
            else if (InheritanceFlags == InheritanceFlags.ObjectInherit & PropagationFlags == PropagationFlags.None)
            {
                return ApplyTo.ThisFolderAndFiles;
            }
            else if (InheritanceFlags == InheritanceFlags.ContainerInherit & PropagationFlags == PropagationFlags.None)
            {
                return ApplyTo.ThisFolderAndSubfolders;
            }
            else if (InheritanceFlags == InheritanceFlags.None & PropagationFlags == PropagationFlags.None)
            {
                return ApplyTo.ThisFolderOnly;
            }
            else if (InheritanceFlags == (InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit) & PropagationFlags == PropagationFlags.None)
            {
                return ApplyTo.ThisFolderSubfoldersAndFiles;
            }

            throw new RightsConverionException("The combination of InheritanceFlags and PropagationFlags could not be translated");
        }

        public static FileSystemRights MapGenericRightsToFileSystemRights(uint originalRights)
        {
            try
            {
                var r = Enum.Parse(typeof(FileSystemRights), (originalRights).ToString());
                if (r.ToString() == originalRights.ToString())
                {
                    throw new ArgumentOutOfRangeException();
                }

                var fileSystemRights = (FileSystemRights)originalRights;
                return fileSystemRights;
            }
            catch (Exception ex)
            {
                FileSystemRights rights = 0;
                if (Convert.ToBoolean((uint)originalRights & (uint)GenericRights.GENERIC_EXECUTE))
                {
                    rights |= (FileSystemRights)MappedGenericRights.FILE_GENERIC_EXECUTE;
                    originalRights ^= (uint)GenericRights.GENERIC_EXECUTE;
                }
                if (Convert.ToBoolean((uint)originalRights & (uint)GenericRights.GENERIC_READ))
                {
                    rights |= (FileSystemRights)MappedGenericRights.FILE_GENERIC_READ;
                    originalRights ^= (uint)GenericRights.GENERIC_READ;
                }
                if (Convert.ToBoolean((uint)originalRights & (uint)GenericRights.GENERIC_WRITE))
                {
                    rights |= (FileSystemRights)MappedGenericRights.FILE_GENERIC_WRITE;
                    originalRights ^= (uint)GenericRights.GENERIC_WRITE;
                }
                if (Convert.ToBoolean((uint)originalRights & (uint)GenericRights.GENERIC_ALL))
                {
                    rights |= (FileSystemRights)MappedGenericRights.FILE_GENERIC_ALL;
                    originalRights ^= (uint)GenericRights.GENERIC_ALL;
                }
                //throw new RightsConverionException("Cannot convert GenericRights into FileSystemRights");

                var remainingRights = (FileSystemRights)Enum.Parse(typeof(FileSystemRights), (originalRights).ToString());

                rights |= remainingRights;

                return rights;
            }
        }
    }
    #endregion

    #region DirectorySecurity2
    //public class DirectorySecurity2 : ICast<DirectorySecurity>, IDisposable
    //{
    //    protected DirectorySecurity securityDescriptor;

    //    public string FullName { get; set; }

    //    public string Name { get { return System.IO.Path.GetFileName(FullName); } }

    //    public DirectorySecurity2() { }
    //    public DirectorySecurity2(DirectorySecurity SecurityDescriptor)
    //    {
    //        this.securityDescriptor = SecurityDescriptor;
    //    }

    //    #region conversion
    //    public static implicit operator DirectorySecurity(DirectorySecurity2 V)
    //    {
    //        return V.securityDescriptor;
    //    }
    //    public static implicit operator DirectorySecurity2(DirectorySecurity n)
    //    {
    //        return new DirectorySecurity2(n);
    //    }
    //    //REQUIRED BECAUSE OF CONVERSION OPERATORS
    //    public override bool Equals(object obj)
    //    {
    //        return this.securityDescriptor == (DirectorySecurity)obj;
    //    }
    //    public override int GetHashCode()
    //    {
    //        return this.securityDescriptor.GetHashCode();
    //    }
    //    #endregion

    //    #region ICast<DirectorySecurity> Members
    //    public DirectorySecurity Cast
    //    {
    //        get { return this.securityDescriptor; }
    //    }
    //    #endregion

    //    #region IDisposable Members
    //    public void Dispose()
    //    { }
    //    #endregion
    //}
    #endregion

    #region FileSystemAccessRule2
    public class FileSystemAccessRule2
    {
        #region Properties
        private FileSystemAccessRule fileSystemAccessRule;
        private string fullName;
        private bool inheritanceEnabled;

        public string Name
        {
            get
            {
                return System.IO.Path.GetFileName(fullName);
            }
        }

        public string FullName
        {
            get { return fullName; }
            set { fullName = value; }
        }

        public bool InheritanceEnabled
        {
            get { return inheritanceEnabled; }
            set { inheritanceEnabled = value; }
        }

        public AccessControlType AccessControlType { get { return fileSystemAccessRule.AccessControlType; } }
        public FileSystemRights2 AccessRights
        {
            get
            {
                var accessRights = (FileSystemRights2)fileSystemAccessRule.FileSystemRights;
                if (accessRights == FileSystemRights2.Synchronize)
                {
                    return FileSystemRights2.None;
                }
                else
                {
                    return accessRights;
                }
            }
        }
        public IdentityReference2 Account { get { return (IdentityReference2)fileSystemAccessRule.IdentityReference; } }
        public InheritanceFlags InheritanceFlags { get { return fileSystemAccessRule.InheritanceFlags; } }
        public bool IsInherited { get { return fileSystemAccessRule.IsInherited; } }
        public PropagationFlags PropagationFlags { get { return fileSystemAccessRule.PropagationFlags; } }
        #endregion

        public FileSystemAccessRule2(FileSystemAccessRule fileSystemAccessRule)
        {
            this.fileSystemAccessRule = fileSystemAccessRule;
        }

        public FileSystemAccessRule2(FileSystemAccessRule fileSystemAccessRule, FileSystemInfo item)
        {
            this.fileSystemAccessRule = fileSystemAccessRule;
            this.fullName = item.FullName;
        }

        public FileSystemAccessRule2(FileSystemAccessRule fileSystemAccessRule, string path)
        {
            this.fileSystemAccessRule = fileSystemAccessRule;
        }

        public static IQueryable<FileSystemAccessRule2> GetFileSystemAccessRules(FileSystemInfo item, bool includeExplicit, bool includeInherited)
        {
            List<FileSystemAccessRule2> acl = new List<FileSystemAccessRule2>();

            if (item as FileInfo != null)
            {
                var file = (FileInfo)item;
                var sd = file.GetAccessControl(AccessControlSections.Access);

                foreach (FileSystemAccessRule ace in sd.GetAccessRules(includeExplicit, includeInherited, typeof(SecurityIdentifier)))
                {
                    var ace2 = new FileSystemAccessRule2(ace) { FullName = file.FullName, InheritanceEnabled = !sd.AreAccessRulesProtected };
                    acl.Add(ace2);
                }

                return acl.AsQueryable();
            }
            else
            {
                DirectoryInfo directory = (DirectoryInfo)item;

                var sd = directory.GetAccessControl(AccessControlSections.Access);

                foreach (FileSystemAccessRule ace in sd.GetAccessRules(includeExplicit, includeInherited, typeof(SecurityIdentifier)))
                {
                    var ace2 = new FileSystemAccessRule2(ace) { FullName = directory.FullName, InheritanceEnabled = !sd.AreAccessRulesProtected };
                    acl.Add(ace2);
                }

                return acl.AsQueryable();
            }
        }

        public static IQueryable<FileSystemAccessRule2> GetFileSystemAccessRules(string path, bool includeExplicit, bool includeInherited)
        {
            if (File.Exists(path))
            {
                var item = new FileInfo(path);
                return GetFileSystemAccessRules(item, includeExplicit, includeInherited);
            }
            else
            {
                var item = new DirectoryInfo(path);
                return GetFileSystemAccessRules(item, includeExplicit, includeInherited);
            }
        }

        public static FileSystemAccessRule2 AddFileSystemAccessRule(FileSystemInfo item, IdentityReference2 account, FileSystemRights rights, AccessControlType type, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags)
        {
            FileSystemAccessRule ace = null;

            if (item as FileInfo != null)
            {
                var file = (FileInfo)item;
                var sd = file.GetAccessControl(AccessControlSections.Access);

                ace = new FileSystemAccessRule((SecurityIdentifier)account, rights, InheritanceFlags.None, PropagationFlags.None, type);
                sd.AddAccessRule(ace);

                file.SetAccessControl(sd);
            }
            else
            {
                DirectoryInfo directory = (DirectoryInfo)item;

                var sd = directory.GetAccessControl(AccessControlSections.Access);

                ace = new FileSystemAccessRule((SecurityIdentifier)account, rights, inheritanceFlags, propagationFlags, type);
                sd.AddAccessRule(ace);

                directory.SetAccessControl(sd);
            }

            return ace;
        }

        public static FileSystemAccessRule2 AddFileSystemAccessRule(FileSystemInfo item, List<IdentityReference2> accounts, FileSystemRights rights, AccessControlType type, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags)
        {
            FileSystemAccessRule ace = null;

            if (item as FileInfo != null)
            {
                var file = (FileInfo)item;
                var sd = file.GetAccessControl(AccessControlSections.Access);

                foreach (var account in accounts)
                {
                    ace = new FileSystemAccessRule((SecurityIdentifier)account, rights, InheritanceFlags.None, PropagationFlags.None, type);
                    sd.AddAccessRule(ace);
                }

                file.SetAccessControl(sd);
            }
            else
            {
                DirectoryInfo directory = (DirectoryInfo)item;

                var sd = directory.GetAccessControl(AccessControlSections.Access);

                foreach (var account in accounts)
                {
                    ace = new FileSystemAccessRule((SecurityIdentifier)account, rights, inheritanceFlags, propagationFlags, type);
                    sd.AddAccessRule(ace);
                }

                directory.SetAccessControl(sd);
            }

            return ace;
        }

        public static FileSystemAccessRule2 AddFileSystemAccessRule(string path, IdentityReference2 account, FileSystemRights rights, AccessControlType type, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags)
        {
            FileSystemAccessRule ace = null;

            if (File.Exists(path))
            {
                var item = new FileInfo(path);
                ace = AddFileSystemAccessRule(item, account, rights, type, inheritanceFlags, propagationFlags);
            }
            else
            {
                var item = new DirectoryInfo(path);
                ace = AddFileSystemAccessRule(item, account, rights, type, inheritanceFlags, propagationFlags);
            }

            return ace;
        }

        public static FileSystemAccessRule2 AddFileSystemAccessRule(string path, List<IdentityReference2> account, FileSystemRights rights, AccessControlType type, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags)
        {
            FileSystemAccessRule ace = null;

            if (File.Exists(path))
            {
                var item = new FileInfo(path);
                ace = AddFileSystemAccessRule(item, account, rights, type, inheritanceFlags, propagationFlags);
            }
            else
            {
                var item = new DirectoryInfo(path);
                ace = AddFileSystemAccessRule(item, account, rights, type, inheritanceFlags, propagationFlags);
            }

            return ace;
        }

        public static void AddFileSystemAccessRule(FileSystemAccessRule2 rule)
        {
            AddFileSystemAccessRule(rule.fullName,
                rule.Account,
                FileSystemSecurity2.MapGenericRightsToFileSystemRights((uint)rule.AccessRights),
                rule.AccessControlType,
                rule.InheritanceFlags,
                rule.PropagationFlags);
        }

        public static void RemoveFileSystemAccessRule(FileSystemInfo item, IdentityReference2 account, FileSystemRights rights, AccessControlType type, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags)
        {
            FileSystemAccessRule ace = null;

            if (item as FileInfo != null)
            {
                var file = (FileInfo)item;
                var sd = file.GetAccessControl(AccessControlSections.Access);

                ace = new FileSystemAccessRule((SecurityIdentifier)account, rights, InheritanceFlags.None, PropagationFlags.None, type);
                sd.RemoveAccessRuleSpecific(ace);

                file.SetAccessControl(sd);
            }
            else
            {
                DirectoryInfo directory = (DirectoryInfo)item;

                var sd = directory.GetAccessControl(AccessControlSections.Access);

                ace = new FileSystemAccessRule((SecurityIdentifier)account, rights, inheritanceFlags, propagationFlags, type);
                sd.RemoveAccessRuleSpecific(ace);

                directory.SetAccessControl(sd);
            }
        }

        public static void RemoveFileSystemAccessRule(FileSystemInfo item, List<IdentityReference2> accounts, FileSystemRights rights, AccessControlType type, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags)
        {
            FileSystemAccessRule ace = null;

            if (item as FileInfo != null)
            {
                var file = (FileInfo)item;
                var sd = file.GetAccessControl(AccessControlSections.Access);

                foreach (var account in accounts)
                {
                    ace = new FileSystemAccessRule((SecurityIdentifier)account, rights, InheritanceFlags.None, PropagationFlags.None, type);
                    sd.RemoveAccessRuleSpecific(ace);
                }

                file.SetAccessControl(sd);
            }
            else
            {
                DirectoryInfo directory = (DirectoryInfo)item;

                var sd = directory.GetAccessControl(AccessControlSections.Access);

                foreach (var account in accounts)
                {
                    ace = new FileSystemAccessRule((SecurityIdentifier)account, rights, inheritanceFlags, propagationFlags, type);
                    sd.RemoveAccessRuleSpecific(ace);
                }

                directory.SetAccessControl(sd);
            }
        }

        public static void RemoveFileSystemAccessRule(string path, IdentityReference2 account, FileSystemRights rights, AccessControlType type, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags)
        {
            if (File.Exists(path))
            {
                var item = new FileInfo(path);
                RemoveFileSystemAccessRule(item, account, rights, type, inheritanceFlags, propagationFlags);
            }
            else
            {
                var item = new DirectoryInfo(path);
                RemoveFileSystemAccessRule(item, account, rights, type, inheritanceFlags, propagationFlags);
            }
        }

        public static void RemoveFileSystemAccessRule(string path, List<IdentityReference2> account, FileSystemRights rights, AccessControlType type, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags)
        {
            if (File.Exists(path))
            {
                var item = new FileInfo(path);
                RemoveFileSystemAccessRule(item, account, rights, type, inheritanceFlags, propagationFlags);
            }
            else
            {
                var item = new DirectoryInfo(path);
                RemoveFileSystemAccessRule(item, account, rights, type, inheritanceFlags, propagationFlags);
            }
        }

        public static void RemoveFileSystemAccessRule(FileSystemInfo item, FileSystemAccessRule ace)
        {
            if (item as FileInfo != null)
            {
                var file = (FileInfo)item;
                var sd = file.GetAccessControl(AccessControlSections.Access);

                sd.RemoveAccessRuleSpecific(ace);

                file.SetAccessControl(sd);
            }
            else
            {
                DirectoryInfo directory = (DirectoryInfo)item;

                var sd = directory.GetAccessControl(AccessControlSections.Access);

                sd.RemoveAccessRuleSpecific(ace);

                directory.SetAccessControl(sd);
            }
        }

        #region Conversion
        public static implicit operator FileSystemAccessRule(FileSystemAccessRule2 ace2)
        {
            return ace2.fileSystemAccessRule;
        }
        public static implicit operator FileSystemAccessRule2(FileSystemAccessRule ace)
        {
            return new FileSystemAccessRule2(ace);
        }
        //REQUIRED BECAUSE OF CONVERSION OPERATORS
        public override bool Equals(object obj)
        {
            return this.fileSystemAccessRule == (FileSystemAccessRule)obj;
        }
        public override int GetHashCode()
        {
            return this.fileSystemAccessRule.GetHashCode();
        }
        public override string ToString()
        {
            return fileSystemAccessRule.ToString();
        }
        public SimpleFileSystemAccessRule ToSimpleFileSystemAccessRule2()
        {
            return new SimpleFileSystemAccessRule(this.fullName, this.Account, this.AccessRights);
        }
        #endregion
    }
    #endregion

    #region FileSystemAuditRule2
    public class FileSystemAuditRule2
    {
        #region Properties
        private FileSystemAuditRule fileSystemAuditRule;
        private string fullName;
        private bool inheritanceEnabled;

        public string Name
        {
            get
            {
                return System.IO.Path.GetFileName(fullName);
            }
        }

        public string FullName
        {
            get { return fullName; }
            set { fullName = value; }
        }

        public bool InheritanceEnabled
        {
            get { return inheritanceEnabled; }
            set { inheritanceEnabled = value; }
        }

        public AuditFlags AuditFlags { get { return fileSystemAuditRule.AuditFlags; } }
        public FileSystemRights2 AccessRights { get { return (FileSystemRights2)fileSystemAuditRule.FileSystemRights; } }
        public IdentityReference2 Account { get { return (IdentityReference2)fileSystemAuditRule.IdentityReference; } }
        public InheritanceFlags InheritanceFlags { get { return fileSystemAuditRule.InheritanceFlags; } }
        public bool IsInherited { get { return fileSystemAuditRule.IsInherited; } }
        public PropagationFlags PropagationFlags { get { return fileSystemAuditRule.PropagationFlags; } }
        #endregion

        public FileSystemAuditRule2(FileSystemAuditRule fileSystemAuditRule)
        {
            this.fileSystemAuditRule = fileSystemAuditRule;
        }

        public FileSystemAuditRule2(FileSystemAuditRule fileSystemAuditRule, FileSystemInfo item)
        {
            this.fileSystemAuditRule = fileSystemAuditRule;
            this.fullName = item.FullName;
        }

        public FileSystemAuditRule2(FileSystemAuditRule fileSystemAuditRule, string path)
        {
            this.fileSystemAuditRule = fileSystemAuditRule;
        }

        public static IQueryable<FileSystemAuditRule2> GetFileSystemAuditRules(FileSystemInfo item, bool includeExplicit, bool includeInherited)
        {
            List<FileSystemAuditRule2> acl = new List<FileSystemAuditRule2>();

            if (item is FileInfo)
            {
                var file = (FileInfo)item;
                var sd = file.GetAccessControl(AccessControlSections.Audit);

                foreach (FileSystemAuditRule ace in sd.GetAuditRules(includeExplicit, includeInherited, typeof(SecurityIdentifier)))
                {
                    var ace2 = new FileSystemAuditRule2(ace) { FullName = file.FullName, InheritanceEnabled = !sd.AreAuditRulesProtected };
                    acl.Add(ace2);
                }

                return acl.AsQueryable();
            }
            else
            {
                DirectoryInfo directory = (DirectoryInfo)item;

                var sd = directory.GetAccessControl(AccessControlSections.Audit);

                foreach (FileSystemAuditRule ace in sd.GetAuditRules(includeExplicit, includeInherited, typeof(SecurityIdentifier)))
                {
                    var ace2 = new FileSystemAuditRule2(ace) { FullName = directory.FullName, InheritanceEnabled = !sd.AreAuditRulesProtected };
                    acl.Add(ace2);
                }

                return acl.AsQueryable();
            }
        }

        public static IQueryable<FileSystemAuditRule2> GetFileSystemAuditRules(string path, bool includeExplicit, bool includeInherited)
        {
            if (File.Exists(path))
            {
                var item = new FileInfo(path);
                return GetFileSystemAuditRules(item, includeExplicit, includeInherited);
            }
            else
            {
                var item = new DirectoryInfo(path);
                return GetFileSystemAuditRules(item, includeExplicit, includeInherited);
            }
        }

        public static FileSystemAuditRule2 AddFileSystemAuditRule(FileSystemInfo item, IdentityReference2 account, FileSystemRights rights, AuditFlags type, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags)
        {
            FileSystemAuditRule ace = null;

            if (item as FileInfo != null)
            {
                var file = (FileInfo)item;
                var sd = file.GetAccessControl(AccessControlSections.Audit);

                ace = new FileSystemAuditRule((SecurityIdentifier)account, rights, InheritanceFlags.None, PropagationFlags.None, type);
                sd.AddAuditRule(ace);

                file.SetAccessControl(sd);
            }
            else
            {
                DirectoryInfo directory = (DirectoryInfo)item;

                var sd = directory.GetAccessControl(AccessControlSections.Audit);

                ace = new FileSystemAuditRule((SecurityIdentifier)account, rights, inheritanceFlags, propagationFlags, type);
                sd.AddAuditRule(ace);

                directory.SetAccessControl(sd);
            }

            return ace;
        }

        public static FileSystemAuditRule2 AddFileSystemAuditRule(string path, IdentityReference2 account, FileSystemRights rights, AuditFlags type, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags)
        {
            FileSystemAuditRule ace = null;

            if (File.Exists(path))
            {
                var item = new FileInfo(path);
                ace = AddFileSystemAuditRule(item, account, rights, type, inheritanceFlags, propagationFlags);
            }
            else
            {
                var item = new DirectoryInfo(path);
                ace = AddFileSystemAuditRule(item, account, rights, type, inheritanceFlags, propagationFlags);
            }

            return ace;
        }

        public static void AddFileSystemAuditRule(FileSystemAuditRule2 rule)
        {
            AddFileSystemAuditRule(rule.fullName,
                rule.Account,
                FileSystemSecurity2.MapGenericRightsToFileSystemRights((uint)rule.AccessRights),
                rule.AuditFlags,
                rule.InheritanceFlags,
                rule.PropagationFlags);
        }

        public static void RemoveFileSystemAuditRule(FileSystemInfo item, IdentityReference2 account, FileSystemRights rights, AuditFlags type, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags)
        {
            FileSystemAuditRule ace = null;

            if (item is FileInfo)
            {
                var file = (FileInfo)item;
                var sd = file.GetAccessControl(AccessControlSections.Audit);

                ace = new FileSystemAuditRule((SecurityIdentifier)account, rights, InheritanceFlags.None, PropagationFlags.None, type);
                sd.RemoveAuditRuleSpecific(ace);

                file.SetAccessControl(sd);
            }
            else
            {
                DirectoryInfo directory = (DirectoryInfo)item;

                var sd = directory.GetAccessControl(AccessControlSections.Audit);

                ace = new FileSystemAuditRule((SecurityIdentifier)account, rights, inheritanceFlags, propagationFlags, type);
                sd.RemoveAuditRuleSpecific(ace);

                directory.SetAccessControl(sd);
            }
        }

        public static void RemoveFileSystemAuditRule(FileSystemInfo item, FileSystemAuditRule ace)
        {
            if (item is FileInfo)
            {
                var file = (FileInfo)item;
                var sd = file.GetAccessControl(AccessControlSections.Audit);

                sd.RemoveAuditRuleSpecific(ace);

                file.SetAccessControl(sd);
            }
            else
            {
                DirectoryInfo directory = (DirectoryInfo)item;

                var sd = directory.GetAccessControl(AccessControlSections.Audit);

                sd.RemoveAuditRuleSpecific(ace);

                directory.SetAccessControl(sd);
            }
        }

        public static void RemoveFileSystemAuditRule(string path, IdentityReference2 account, FileSystemRights rights, AuditFlags type, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags)
        {
            if (File.Exists(path))
            {
                var item = new FileInfo(path);
                RemoveFileSystemAuditRule(item, account, rights, type, inheritanceFlags, propagationFlags);
            }
            else
            {
                var item = new DirectoryInfo(path);
                RemoveFileSystemAuditRule(item, account, rights, type, inheritanceFlags, propagationFlags);
            }
        }

        #region Conversion
        public static implicit operator FileSystemAuditRule(FileSystemAuditRule2 ace2)
        {
            return ace2.fileSystemAuditRule;
        }
        public static implicit operator FileSystemAuditRule2(FileSystemAuditRule ace)
        {
            return new FileSystemAuditRule2(ace);
        }
        //REQUIRED BECAUSE OF CONVERSION OPERATORS
        public override bool Equals(object obj)
        {
            return this.fileSystemAuditRule == (FileSystemAuditRule)obj;
        }
        public override int GetHashCode()
        {
            return this.fileSystemAuditRule.GetHashCode();
        }
        public override string ToString()
        {
            return fileSystemAuditRule.ToString();
        }
        public SimpleFileSystemAuditRule ToSimpleFileSystemAuditRule2()
        {
            return new SimpleFileSystemAuditRule(this.fullName, this.Account, this.AccessRights);
        }
        #endregion
    }
    #endregion

    #region SimpleFileSystemAccessRule
    public class SimpleFileSystemAccessRule
    {
        private string fullName;
        private IdentityReference2 identity;
        private FileSystemRights2 accessRights;
        private AccessControlType type;

        public AccessControlType AccessControlType
        {
            get { return type; }
            set { type = value; }
        }

        public string FullName
        {
            get { return fullName; }
        }

        public string Name
        {
            get
            {
                return System.IO.Path.GetFileName(fullName);
            }
        }

        public IdentityReference2 Identity
        {
            get { return identity; }
        }

        public SimpleFileSystemAccessRights AccessRights
        {
            get
            {
                SimpleFileSystemAccessRights result = SimpleFileSystemAccessRights.None;

                if ((accessRights & FileSystemRights2.Read) == FileSystemRights2.Read)
                { result |= SimpleFileSystemAccessRights.Read; }

                if ((accessRights & FileSystemRights2.CreateFiles) == FileSystemRights2.CreateFiles)
                { result |= SimpleFileSystemAccessRights.Write; }

                if ((accessRights & FileSystemRights2.AppendData) == FileSystemRights2.AppendData)
                { result |= SimpleFileSystemAccessRights.Write; }

                if ((accessRights & FileSystemRights2.ReadExtendedAttributes) == FileSystemRights2.ReadExtendedAttributes)
                { result |= SimpleFileSystemAccessRights.Read; }

                if ((accessRights & FileSystemRights2.WriteExtendedAttributes) == FileSystemRights2.WriteExtendedAttributes)
                { result |= SimpleFileSystemAccessRights.Write; }

                if ((accessRights & FileSystemRights2.ExecuteFile) == FileSystemRights2.ExecuteFile)
                { result |= SimpleFileSystemAccessRights.Read; }

                if ((accessRights & FileSystemRights2.DeleteSubdirectoriesAndFiles) == FileSystemRights2.DeleteSubdirectoriesAndFiles)
                { result |= SimpleFileSystemAccessRights.Delete; }

                if ((accessRights & FileSystemRights2.ReadAttributes) == FileSystemRights2.ReadAttributes)
                { result |= SimpleFileSystemAccessRights.Read; }

                if ((accessRights & FileSystemRights2.WriteAttributes) == FileSystemRights2.WriteAttributes)
                { result |= SimpleFileSystemAccessRights.Write; }

                if ((accessRights & FileSystemRights2.Delete) == FileSystemRights2.Delete)
                { result |= SimpleFileSystemAccessRights.Delete; }

                if ((accessRights & FileSystemRights2.ReadPermissions) == FileSystemRights2.ReadPermissions)
                { result |= SimpleFileSystemAccessRights.Read; }

                if ((accessRights & FileSystemRights2.ChangePermissions) == FileSystemRights2.ChangePermissions)
                { result |= SimpleFileSystemAccessRights.Write; }

                if ((accessRights & FileSystemRights2.TakeOwnership) == FileSystemRights2.TakeOwnership)
                { result |= SimpleFileSystemAccessRights.Write; }

                if ((accessRights & FileSystemRights2.Synchronize) == FileSystemRights2.Synchronize)
                { result |= SimpleFileSystemAccessRights.Read; }

                if ((accessRights & FileSystemRights2.FullControl) == FileSystemRights2.FullControl)
                { result = (SimpleFileSystemAccessRights.Write | SimpleFileSystemAccessRights.Read | SimpleFileSystemAccessRights.Delete); }

                if ((accessRights & FileSystemRights2.GenericRead) == FileSystemRights2.GenericRead)
                { result |= SimpleFileSystemAccessRights.Read; }

                if ((accessRights & FileSystemRights2.GenericWrite) == FileSystemRights2.GenericWrite)
                { result |= SimpleFileSystemAccessRights.Write; }

                if ((accessRights & FileSystemRights2.GenericExecute) == FileSystemRights2.GenericExecute)
                { result |= SimpleFileSystemAccessRights.Read; }

                if ((accessRights & FileSystemRights2.GenericAll) == FileSystemRights2.GenericAll)
                { result = (SimpleFileSystemAccessRights.Write | SimpleFileSystemAccessRights.Read | SimpleFileSystemAccessRights.Delete); }

                return result;
            }
        }

        public SimpleFileSystemAccessRule(string Path, IdentityReference2 account, FileSystemRights2 access)
        {
            this.fullName = Path;
            this.accessRights = access;
            this.identity = account;
        }

        public override bool Equals(object obj)
        {
            var compareObject = obj as SimpleFileSystemAccessRule;

            if (compareObject == null)
            {
                return false;
            }

            if (this.AccessRights == compareObject.AccessRights && this.Identity == compareObject.Identity && this.AccessControlType == compareObject.AccessControlType)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public override int GetHashCode()
        {
            return this.Identity.GetHashCode() | this.AccessRights.GetHashCode() | this.AccessControlType.GetHashCode();
        }
    }
    #endregion

    #region SimpleFileSystemAuditRule
    public class SimpleFileSystemAuditRule
    {
        private string fullName;
        private IdentityReference2 identity;
        private FileSystemRights2 accessRights;
        private AccessControlType type;

        public AccessControlType AccessControlType
        {
            get { return type; }
            set { type = value; }
        }

        public string FullName
        {
            get { return fullName; }
        }

        public string Name
        {
            get
            {
                return System.IO.Path.GetFileName(fullName);
            }
        }

        public IdentityReference2 Identity
        {
            get { return identity; }
        }

        public SimpleFileSystemAccessRights AccessRights
        {
            get
            {
                SimpleFileSystemAccessRights result = SimpleFileSystemAccessRights.None;

                if ((accessRights & FileSystemRights2.Read) == FileSystemRights2.Read)
                { result |= SimpleFileSystemAccessRights.Read; }

                if ((accessRights & FileSystemRights2.CreateFiles) == FileSystemRights2.CreateFiles)
                { result |= SimpleFileSystemAccessRights.Write; }

                if ((accessRights & FileSystemRights2.AppendData) == FileSystemRights2.AppendData)
                { result |= SimpleFileSystemAccessRights.Write; }

                if ((accessRights & FileSystemRights2.ReadExtendedAttributes) == FileSystemRights2.ReadExtendedAttributes)
                { result |= SimpleFileSystemAccessRights.Read; }

                if ((accessRights & FileSystemRights2.WriteExtendedAttributes) == FileSystemRights2.WriteExtendedAttributes)
                { result |= SimpleFileSystemAccessRights.Write; }

                if ((accessRights & FileSystemRights2.ExecuteFile) == FileSystemRights2.ExecuteFile)
                { result |= SimpleFileSystemAccessRights.Read; }

                if ((accessRights & FileSystemRights2.DeleteSubdirectoriesAndFiles) == FileSystemRights2.DeleteSubdirectoriesAndFiles)
                { result |= SimpleFileSystemAccessRights.Delete; }

                if ((accessRights & FileSystemRights2.ReadAttributes) == FileSystemRights2.ReadAttributes)
                { result |= SimpleFileSystemAccessRights.Read; }

                if ((accessRights & FileSystemRights2.WriteAttributes) == FileSystemRights2.WriteAttributes)
                { result |= SimpleFileSystemAccessRights.Write; }

                if ((accessRights & FileSystemRights2.Delete) == FileSystemRights2.Delete)
                { result |= SimpleFileSystemAccessRights.Delete; }

                if ((accessRights & FileSystemRights2.ReadPermissions) == FileSystemRights2.ReadPermissions)
                { result |= SimpleFileSystemAccessRights.Read; }

                if ((accessRights & FileSystemRights2.ChangePermissions) == FileSystemRights2.ChangePermissions)
                { result |= SimpleFileSystemAccessRights.Write; }

                if ((accessRights & FileSystemRights2.TakeOwnership) == FileSystemRights2.TakeOwnership)
                { result |= SimpleFileSystemAccessRights.Write; }

                if ((accessRights & FileSystemRights2.Synchronize) == FileSystemRights2.Synchronize)
                { result |= SimpleFileSystemAccessRights.Read; }

                if ((accessRights & FileSystemRights2.FullControl) == FileSystemRights2.FullControl)
                { result = (SimpleFileSystemAccessRights.Write | SimpleFileSystemAccessRights.Read | SimpleFileSystemAccessRights.Delete); }

                if ((accessRights & FileSystemRights2.GenericRead) == FileSystemRights2.GenericRead)
                { result |= SimpleFileSystemAccessRights.Read; }

                if ((accessRights & FileSystemRights2.GenericWrite) == FileSystemRights2.GenericWrite)
                { result |= SimpleFileSystemAccessRights.Write; }

                if ((accessRights & FileSystemRights2.GenericExecute) == FileSystemRights2.GenericExecute)
                { result |= SimpleFileSystemAccessRights.Read; }

                if ((accessRights & FileSystemRights2.GenericAll) == FileSystemRights2.GenericAll)
                { result = (SimpleFileSystemAccessRights.Write | SimpleFileSystemAccessRights.Read | SimpleFileSystemAccessRights.Delete); }

                return result;
            }
        }

        public SimpleFileSystemAuditRule(string Path, IdentityReference2 account, FileSystemRights2 access)
        {
            this.fullName = Path;
            this.accessRights = access;
            this.identity = account;
        }

        public override bool Equals(object obj)
        {
            var compareObject = obj as SimpleFileSystemAccessRule;

            if (compareObject == null)
            {
                return false;
            }

            if (this.AccessRights == compareObject.AccessRights && this.Identity == compareObject.Identity && this.AccessControlType == compareObject.AccessControlType)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public override int GetHashCode()
        {
            return this.Identity.GetHashCode() | this.AccessRights.GetHashCode() | this.AccessControlType.GetHashCode();
        }
    }
    #endregion

    #region FileSystemAccessInheritanceInfo
    public class FileSystemAccessInheritanceInfo
    {

        private FileSystemInfo item;
        private bool inheritanceEnabled;

        public FileSystemInfo Item
        {
            get { return item; }
            set { item = value; }
        }

        public bool InheritanceEnabled
        {
            get { return inheritanceEnabled; }
            set { inheritanceEnabled = value; }
        }

        public string FullName { get { return Item.FullName; } }

        public string Name { get { return Path.GetFileName(item.FullName); } }

        public FileSystemAccessInheritanceInfo(string Path)
        {
            if (File.Exists(Path))
            {
                item = new FileInfo(Path);
                inheritanceEnabled = !((FileInfo)item).GetAccessControl(AccessControlSections.Access).AreAccessRulesProtected;
            }
            else if (Directory.Exists(Path))
            {
                item = new DirectoryInfo(Path);
                inheritanceEnabled = !((DirectoryInfo)item).GetAccessControl(AccessControlSections.Access).AreAccessRulesProtected;
            }
        }

        public FileSystemAccessInheritanceInfo(FileSystemInfo Item)
        {
            if (Item as FileInfo != null)
            {
                this.item = Item;
                inheritanceEnabled = !((FileInfo)item).GetAccessControl(AccessControlSections.Access).AreAccessRulesProtected;
            }
            else if (Item as DirectoryInfo != null)
            {
                this.item = Item;
                inheritanceEnabled = !((DirectoryInfo)item).GetAccessControl(AccessControlSections.Access).AreAccessRulesProtected;
            }
        }

        public void EnableInheritance(bool RemoveExplicitAccessRules)
        {
            if (item as FileInfo != null)
            {
                var sd = ((FileInfo)item).GetAccessControl(AccessControlSections.Access);
                sd.SetAccessRuleProtection(false, false);

                //if RemoveExplicitAccessRules is set
                if (RemoveExplicitAccessRules)
                {
                    //remove all explicitly set ACEs from the item
                    foreach (FileSystemAccessRule ace in sd.GetAccessRules(true, false, typeof(SecurityIdentifier)))
                    {
                        sd.RemoveAccessRule(ace);
                    }
                }

                ((FileInfo)item).SetAccessControl(sd);

                //refresh the inheritance info by reading it again from the item
                inheritanceEnabled = !((FileInfo)item).GetAccessControl(AccessControlSections.Access).AreAccessRulesProtected;
            }
            else if (item as DirectoryInfo != null)
            {
                var sd = ((DirectoryInfo)item).GetAccessControl(AccessControlSections.Access);
                sd.SetAccessRuleProtection(false, false);

                //if RemoveExplicitAccessRules is set
                if (RemoveExplicitAccessRules)
                {
                    //remove all explicitly set ACEs from the item
                    foreach (FileSystemAccessRule ace in sd.GetAccessRules(true, false, typeof(SecurityIdentifier)))
                    {
                        sd.RemoveAccessRule(ace);
                    }
                }

                ((DirectoryInfo)item).SetAccessControl(sd);

                //refresh the inheritance info by reading it again from the item
                inheritanceEnabled = !((DirectoryInfo)item).GetAccessControl(AccessControlSections.Access).AreAccessRulesProtected;
            }
        }

        public void DisableInheritance(bool preserveInheritedAccessRules)
        {
            if (item as FileInfo != null)
            {
                var sd = ((FileInfo)item).GetAccessControl(AccessControlSections.Access);

                sd.SetAccessRuleProtection(true, preserveInheritedAccessRules);

                ((FileInfo)item).SetAccessControl(sd);

                //refresh the inheritance info by reading it again from the item
                inheritanceEnabled = !((FileInfo)item).GetAccessControl(AccessControlSections.Access).AreAccessRulesProtected;
            }
            else if (item as DirectoryInfo != null)
            {
                var sd = ((DirectoryInfo)item).GetAccessControl(AccessControlSections.Access);

                sd.SetAccessRuleProtection(true, preserveInheritedAccessRules);

                ((DirectoryInfo)item).SetAccessControl(sd);

                //refresh the inheritance info by reading it again from the item
                inheritanceEnabled = !((DirectoryInfo)item).GetAccessControl(AccessControlSections.Access).AreAccessRulesProtected;
            }
        }
    }
    #endregion

    #region FileSystemAuditInheritanceInfo
    public class FileSystemAuditInheritanceInfo
    {

        private FileSystemInfo item;
        private bool inheritanceEnabled;

        public FileSystemInfo Item
        {
            get { return item; }
            set { item = value; }
        }

        public bool InheritanceEnabled
        {
            get { return inheritanceEnabled; }
            set { inheritanceEnabled = value; }
        }

        public string FullName { get { return Item.FullName; } }

        public string Name { get { return Path.GetFileName(item.FullName); } }

        public FileSystemAuditInheritanceInfo(string Path)
        {
            if (File.Exists(Path))
            {
                item = new FileInfo(Path);
                inheritanceEnabled = !((FileInfo)item).GetAccessControl(AccessControlSections.Audit).AreAuditRulesProtected;
            }
            else if (Directory.Exists(Path))
            {
                item = new DirectoryInfo(Path);
                inheritanceEnabled = !((DirectoryInfo)item).GetAccessControl(AccessControlSections.Audit).AreAuditRulesProtected;
            }
        }

        public FileSystemAuditInheritanceInfo(FileSystemInfo Item)
        {
            if (Item as FileInfo != null)
            {
                this.item = Item;
                inheritanceEnabled = !((FileInfo)item).GetAccessControl(AccessControlSections.Audit).AreAuditRulesProtected;
            }
            else if (Item as DirectoryInfo != null)
            {
                this.item = Item;
                inheritanceEnabled = !((DirectoryInfo)item).GetAccessControl(AccessControlSections.Audit).AreAuditRulesProtected;
            }
        }

        public void EnableInheritance(bool RemoveExplicitAccessRules)
        {
            if (item as FileInfo != null)
            {
                var sd = ((FileInfo)item).GetAccessControl(AccessControlSections.Audit);
                sd.SetAuditRuleProtection(false, false);

                //if RemoveExplicitAccessRules is set
                if (RemoveExplicitAccessRules)
                {
                    //remove all explicitly set ACEs from the item
                    foreach (FileSystemAuditRule ace in sd.GetAuditRules(true, false, typeof(SecurityIdentifier)))
                    {
                        sd.RemoveAuditRule(ace);
                    }
                }

                ((FileInfo)item).SetAccessControl(sd);

                //refresh the inheritance info by reading it again from the item
                inheritanceEnabled = !((FileInfo)item).GetAccessControl(AccessControlSections.Audit).AreAuditRulesProtected;
            }
            else if (item as DirectoryInfo != null)
            {
                var sd = ((DirectoryInfo)item).GetAccessControl(AccessControlSections.Audit);
                sd.SetAuditRuleProtection(false, false);

                //if RemoveExplicitAccessRules is set
                if (RemoveExplicitAccessRules)
                {
                    //remove all explicitly set ACEs from the item
                    foreach (FileSystemAuditRule ace in sd.GetAuditRules(true, false, typeof(SecurityIdentifier)))
                    {
                        sd.RemoveAuditRule(ace);
                    }
                }

                ((DirectoryInfo)item).SetAccessControl(sd);

                //refresh the inheritance info by reading it again from the item
                inheritanceEnabled = !((DirectoryInfo)item).GetAccessControl(AccessControlSections.Audit).AreAuditRulesProtected;
            }
        }

        public void DisableInheritance(bool preserveInheritedAccessRules)
        {
            if (item as FileInfo != null)
            {
                var sd = ((FileInfo)item).GetAccessControl(AccessControlSections.Audit);

                sd.SetAuditRuleProtection(true, preserveInheritedAccessRules);

                ((FileInfo)item).SetAccessControl(sd);

                //refresh the inheritance info by reading it again from the item
                inheritanceEnabled = !((FileInfo)item).GetAccessControl(AccessControlSections.Audit).AreAuditRulesProtected;
            }
            else if (item as DirectoryInfo != null)
            {
                var sd = ((DirectoryInfo)item).GetAccessControl(AccessControlSections.Audit);

                sd.SetAuditRuleProtection(true, preserveInheritedAccessRules);

                ((DirectoryInfo)item).SetAccessControl(sd);

                //refresh the inheritance info by reading it again from the item
                inheritanceEnabled = !((DirectoryInfo)item).GetAccessControl(AccessControlSections.Audit).AreAuditRulesProtected;
            }
        }
    }
    #endregion

    #region FileSystemEffectivePermissionEntry
    public class FileSystemEffectivePermissionEntry
    {
        private IdentityReference2 account;
        private uint accessMask;
        private string objectPath;

        public IdentityReference2 Account { get { return account; } }

        public uint AccessMask { get { return accessMask; } }

        public string FullName { get { return objectPath; } }

        public string Name
        {
            get
            {
                if (!string.IsNullOrEmpty(FullName))
                {
                    return System.IO.Path.GetFileName(FullName);
                }
                else
                {
                    return null;
                }
            }
        }

        public FileSystemRights AccessRights
        {
            get
            {
                return (FileSystemRights)accessMask;
            }
        }

        private List<string> accessAsString;
        public List<string> AccessAsString { get { return accessAsString; } }

        public FileSystemEffectivePermissionEntry(IdentityReference2 identity, uint AccessMask, string FullName)
        {
            this.account = identity;
            this.accessMask = AccessMask;
            this.objectPath = FullName;
            this.accessAsString = new List<string>();

            if (accessMask == 0)
            {
                accessAsString.Add("None");
            }
            else
            {
                string tempString = ((FileSystemRights)this.accessMask).ToString();
                foreach (var s in tempString.Split(','))
                {
                    this.accessAsString.Add(s);
                }
            }
        }
    }
    #endregion

    #region FileSystemOwner
    public class FileSystemOwner
    {
        private FileSystemInfo item;
        private IdentityReference2 owner;
        private FileSystemSecurity sd;

        public FileSystemInfo Item
        {
            get { return item; }
            set { item = value; }
        }

        public IdentityReference2 Owner
        {
            get { return owner; }
            set { owner = value; }
        }

        public FileSystemOwner(string Path)
        {
            if (File.Exists(Path))
            {
                item = new FileInfo(Path);
                owner = ((FileInfo)item).GetAccessControl(AccessControlSections.Owner).GetOwner(typeof(SecurityIdentifier));
            }
            else if (Directory.Exists(Path))
            {
                item = new DirectoryInfo(Path);
                owner = ((DirectoryInfo)item).GetAccessControl(AccessControlSections.Owner).GetOwner(typeof(SecurityIdentifier));
            }
        }

        public FileSystemOwner(FileSystemInfo Item)
        {
            this.item = Item;

            if (Item as FileInfo != null)
            {

                try
                {
                    sd = (FileSecurity)((FileInfo)item).GetAccessControl(AccessControlSections.Owner);
                    owner = ((FileSecurity)sd).GetOwner(typeof(SecurityIdentifier));
                }
                catch
                {
                    sd = new FileSecurity();
                }
            }
            else if (Item as DirectoryInfo != null)
            {
                try
                {
                    sd = (DirectorySecurity)((DirectoryInfo)item).GetAccessControl(AccessControlSections.Owner);
                    owner = ((DirectorySecurity)sd).GetOwner(typeof(SecurityIdentifier));
                }
                catch
                {
                    //sd = new DirectorySecurity(item.FullName, AccessControlSections.Owner);
                    sd = new DirectorySecurity();
                }
            }
        }

        public void SetOwner(IdentityReference2 Account)
        {
            if (item as FileInfo != null)
            {
                sd.SetOwner(Account);
                ((FileInfo)item).SetAccessControl((FileSecurity)sd);

            }
            else if (item as DirectoryInfo != null)
            {
                sd.SetOwner(Account);
                ((DirectoryInfo)item).SetAccessControl((DirectorySecurity)sd);
            }
        }
    }
    #endregion
}